#ifndef __SYLAR_THREAD_H__
#define __SYLAR_THREAD_H__

#include <thread>
#include <functional>
#include <memory>
#include <atomic>
#include <pthread.h>
#include <semaphore.h>
#include <stdint.h>

namespace sylar {

// 信号量
class Semaphore {
public:
  Semaphore(uint32_t count = 0);
  ~Semaphore();

  // 等待信号量
  void wait();
  // 发出通知
  void notify();
private:
  // 禁止拷贝和赋值
  Semaphore(const Semaphore&) = delete;
  Semaphore(const Semaphore&&) = delete;
  Semaphore& operator=(const Semaphore&) = delete;
private:
  sem_t m_semaphore;
};

// 互斥包装器，构造时加锁，析构时解锁
template<class T>
struct ScopedLockImpl {
public:
  ScopedLockImpl(T& mutex)
    :m_mutex(mutex) {
    // 构造时上锁
    m_mutex.lock();
    m_locked = true;
  }

  // 析构时解锁，防止临界区抛出异常导致未解锁
  ~ScopedLockImpl() {
    unlock();
  }

  // 使用者也可以自行上锁
  void lock() {
    if (!m_locked) {
      m_mutex.lock();
      m_locked = true;
    }
  }

  // 使用者也可以自行解锁
  void unlock() {
    if (m_locked) {
      m_mutex.unlock();
      m_locked = false;
    }
  }

private:
  T& m_mutex;
  // 判断是否已锁
  bool m_locked;
};

// 读锁
template<class T>
struct ReadScopedLockImpl {
public:
  ReadScopedLockImpl(T& mutex)
    :m_mutex(mutex) {
    // 使用 rdlock 加读锁
    m_mutex.rdlock();
    m_locked = true;
  }

  ~ReadScopedLockImpl() {
    unlock();
  }

  void lock() {
    if(!m_locked) {
      // 使用 rdlock 加读锁
      m_mutex.rdlock();
      m_locked = true;
    }
  }

  void unlock() {
    if(m_locked) {
      m_mutex.unlock();
      m_locked = false;
    }
  }
private:
  T& m_mutex;
  // 判断是否已锁
  bool m_locked;
};

// 写锁
template<class T>
struct WriteScopedLockImpl {
public:
  WriteScopedLockImpl(T& mutex)
    :m_mutex(mutex) {
    // 使用 wrlock 加写锁
    m_mutex.wrlock();
    m_locked = true;
  }

  ~WriteScopedLockImpl() {
    unlock();
  }

  void lock() {
    if(!m_locked) {
      // 使用 wrlock 加写锁
      m_mutex.wrlock();
      m_locked = true;
    }
  }

  void unlock() {
    if(m_locked) {
      m_mutex.unlock();
      m_locked = false;
    }
  }
private:
  T& m_mutex;
  bool m_locked;
};

// 互斥量
class Mutex {
public:
  typedef ScopedLockImpl<Mutex> Lock;
  Mutex() {
    pthread_mutex_init(&m_mutex, nullptr);
  }

  ~Mutex() {
    pthread_mutex_destroy(&m_mutex);
  }

  void lock() {
    pthread_mutex_lock(&m_mutex);
  }

  void unlock() {
    pthread_mutex_unlock(&m_mutex);
  }
private:
  pthread_mutex_t m_mutex;
};

// 一个空的互斥量，用于测试
class NullMutex {
public:
  typedef ScopedLockImpl<NullMutex> Lock;
  NullMutex() {}
  ~NullMutex() {}
  void lock() {}
  void unlock() {}
};

// 读写锁
class RWMutex {
public:
  // 读锁
  typedef ReadScopedLockImpl<RWMutex> ReadLock;
  // 写锁
  typedef WriteScopedLockImpl<RWMutex> WriteLock;

  RWMutex() {
    pthread_rwlock_init(&m_lock, nullptr);
  }
  
  ~RWMutex() {
    pthread_rwlock_destroy(&m_lock);
  }

  void rdlock() {
    pthread_rwlock_rdlock(&m_lock);
  }

  void wrlock() {
    pthread_rwlock_wrlock(&m_lock);
  }

  void unlock() {
    pthread_rwlock_unlock(&m_lock);
  }
private:
  pthread_rwlock_t m_lock;
};

// 空的读写锁，只提供接口，用于测试
class NullRWMutex {
public:
  typedef ReadScopedLockImpl<NullMutex> ReadLock;
  typedef WriteScopedLockImpl<NullMutex> WriteLock;

  NullRWMutex() {}
  ~NullRWMutex() {}

  void rdlock() {}
  void wrlock() {}
  void unlock() {}
};

// 自旋锁
class Spinlock {
public:
  typedef ScopedLockImpl<Spinlock> Lock;
  Spinlock() {
    pthread_spin_init(&m_mutex, 0);
  }

  ~Spinlock() {
    pthread_spin_destroy(&m_mutex);
  }

  void lock() {
    pthread_spin_lock(&m_mutex);
  }

  void unlock() {
    pthread_spin_unlock(&m_mutex);
  }
private:
  pthread_spinlock_t m_mutex;
};

// 原子类型锁
class CASLock {
public:
  typedef ScopedLockImpl<CASLock> Lock;
  CASLock() {
    m_mutex.clear();
  }
  ~CASLock() {
  }

  void lock() {
    while(std::atomic_flag_test_and_set_explicit(&m_mutex, std::memory_order_acquire));
  }

  void unlock() {
    std::atomic_flag_clear_explicit(&m_mutex, std::memory_order_release);
  }
private:
  volatile std::atomic_flag m_mutex;
};

// 封装 pthread
class Thread {
public:
  typedef std::shared_ptr<Thread> ptr;
  Thread(std::function<void()> cb, const std::string& name);
  ~Thread();

  pid_t getId() const { return m_id;}
  const std::string& getName() const { return m_name;}

  void join();

  // 获取当前线程
  static Thread* GetThis();
  // 获取当前线程名称（给 log 使用）
  static const std::string& GetName();
  // 设置当前线程名称
  static void SetName(const std::string& name);
private:
  // 禁止拷贝和赋值
  Thread(const Thread&) = delete;
  Thread(const Thread&&) = delete;
  Thread& operator=(const Thread&) = delete;

  static void* run(void* arg);
private:
  // 线程 id
  pid_t m_id = -1;
  // 线程
  pthread_t m_thread = 0;
  std::function<void()> m_cb;
  // 线程名
  std::string m_name;
  Semaphore m_semaphore;
};

}

#endif
